package com.example.yx.demo15;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

public class A15 {

    public static void main(String[] args) {
        /*
            两个切面概念：
            aspect =
                通知1（advice） + 切点1（pointcut）
                通知2（advice） + 切点2（pointcut）
                通知3（advice） + 切点3（pointcut）
                ...
                advisor = 更细粒度的切面，包含一个通知和切点
         */

        //1.备好切点
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(* foo())");

        //2.备好通知

        MethodInterceptor interceptor = invocation -> {
            System.out.println("before...");
            Object result = invocation.proceed();
            System.out.println("after...");
            return result;
        };
        //3.备好切面

        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut,interceptor);

        /*
        4.创建代理
        ProxyFactory继承了ProxyConfig，在ProxyConfig中有一个属性：private boolean proxyTargetClass = false;
            a.proxyTargetClass = false，目标实现了接口，用jdk来生成代理（jdk必须实现接口来生成代理）
            b.proxyTargetClass = false，目标没有实现接口，用cglib生成代理
            c.proxyTargetClass = true，不管有没有实现接口，总是用cglib
         */
        Target1 target1 = new Target1();
        ProxyFactory factory = new ProxyFactory();
        factory.setTarget(target1);
        factory.setInterfaces(target1.getClass().getInterfaces());
        factory.setProxyTargetClass(true);
        factory.addAdvisor(advisor);

        I1 proxy = (I1) factory.getProxy();
        System.out.println(proxy.getClass());
        proxy.foo();
        proxy.bar();



    }

    interface I1 {
        void foo();
        void bar();
    }

    static class Target1 implements I1{

        @Override
        public void foo() {
            System.out.println("target 1 foo()");
        }

        @Override
        public void bar() {
            System.out.println("target 1 bar()");
        }
    }
    static class Target2 implements I1{

        @Override
        public void foo() {
            System.out.println("target 2 foo()");
        }

        @Override
        public void bar() {
            System.out.println("target 2 bar()");
        }
    }
}
